#ifndef CODEVIEW_HPP
#define CODEVIEW_HPP

#include <QDockWidget>
#include <QScrollBar>
#include <QPoint>
#include <QTextBlock>
#include <QTextCursor>
#include <QTextBlockFormat>
#include <QBrush>
#include <QColor>
#include <QMap>
#include <QToolTip>

#include "command.hpp"
#include "programmanagement.hpp"
#include "textediteventhandler.hpp"
#include "tooltipeventhandler.hpp"
#include "highlighter.hpp"
#include "pix.hpp"

class Pix;

namespace Ui {
    class CodeView;
}

/**
* @brief QDockWidget CodeView representing the contents of the loaded LST file
* @details This DockWidget contains the LST file. Two Textareas are shown to seperate line numbers \n
* from the real program code. These two areas are synchronized so that scrolling will be synchronous. \n
* The anchors for the CodeBlock is the programMemory address (not shown) which is mainly used to jump \n
* to a specific line of code. Other lines (comments, blank, equ) cannot be accessed via an anchor tag.
*
* @class CodeView codeview.hpp "codeview.hpp"
*/
class CodeView : public QDockWidget {
    Q_OBJECT
public:
    /**
    * @brief Constructor for CodeView
    *
    * @fn CodeView(Pix *pix, QWidget *parent = 0)
    * @param pix
    * @param parent
    */
    CodeView(QWidget *parent = 0);

    /**
    * @brief Destructor for CodeView
    *
    * @fn ~CodeView
    */
    ~CodeView();

    /**
    * @brief Adds a new Command to the CodeView
    *
    * @fn void addCommands(const QList<Command> *commandList)
    * @param commandList
    */
    void addCommands(const QList<Command> *commandList);

    /**
    * @brief Reset all shown GUI Elements
    *
    * @fn reset
    */
    void reset();

    /**
    * @brief Highlights the Line at the position p1,p2
    *
    * @fn void highlightLines(int p1, int p2)
    * @param p1
    * @param p2
    */
    void highlightLines(int p1, int p2);

protected:
    /**
    * @brief Action on ChangeEvent
    *
    * @fn void changeEvent(QEvent *e)
    * @param e
    */
    void changeEvent(QEvent *e);

private:
    Ui::CodeView *ui;
    TextEditEventHandler *textEditEventHandler;
    ToolTipEventHandler *tooltipEventHandler;
    Highlighter *highlighter;
    QTextBlockFormat *highlightFormat;
    QTextBlockFormat *currentLineFormat;
    QMap<QString, QString> tooltipMap;
    QMap<QString, int> anchorMap;
    bool highlightedLines;
    bool highlightedPc;
    int simulationStoppedOnLine;

    /**
    * @brief Adds a new commandline to codeview
    *
    * @fn void addCommandLine(const Command &command)
    * @param commandLine
    */
    void addCommandLine(const Command &command);

public slots:
    /**
    * @brief Slot called when a custom variable / label has been found to highlight it correctly
    *
    * @fn onCustomHighlightingRule
    * @param pattern
    * @param type
    */
    void onCustomHighlightingRule(QString pattern, int type);

    /**
    * @brief Slot called when a Breakpoint has been added / removed from the Breakpoint-List
    *
    * @fn onBreakpointToggled
    * @param line
    * @param add
    */
    void onBreakpointToggled(int line, bool add);

    /**
    * @brief Slot called when the PC changes. This will highlight the current line
    *
    * @fn onProgramCounterChanged
    * @param pc
    */
    void onProgramCounterChanged(int pc);

    /**
    * @brief Slot called when a variable / label has been found / changed. Will show a tooltip for this variable containing the address and value
    *
    * @fn onCustomTooltip
    * @param item
    * @param tooltip
    */
    void onCustomTooltip(QString item, QString tooltip);

    /**
    * @brief Slot called when Pix starts / stops execution of the program. Needed to show the last executed line
    *
    * @fn onSimulationStateChanged
    * @param state
    * @param pc
    */
    void onSimulationStateChanged(bool state, int pc);

    /**
    * @brief Slot called when the user wants to jump to a Breakpoint
    *
    * @fn onJumpToBreakpoint
    * @param anchor
    */
    void onJumpToBreakpoint(QString anchor);

private slots:
    /**
    * @brief Slot called when the user has triggered a Breakpoint at the Point
    *
    * @fn onRequestBreakpoint
    * @param point
    */
    void onRequestBreakpoint(QPoint point);

    /**
    * @brief User selects one (or more) lines with left mouse click / release
    *
    * @fn onRequestHighlightLine
    * @param point
    * @param startPoint
    */
    void onRequestHighlightLine(QPoint point, QPoint startPoint);

    /**
    * @brief Unhighlights all current highlighted lines
    *
    * @fn onRequestUnHighlightLine
    */
    void onRequestUnHighlightLine();

    /**
    * @brief Slot called when the user moves the mouse over a item (Shows the tooltip)
    *
    * @fn onTooltipRequested
    * @param point
    */
    void onTooltipRequested(QPoint *point);

signals:
    /**
    * @brief Emitted to signal that the user has toggled a Breakpoint at the specified line
    *
    * @fn requestBreakpoint
    * @param line
    */
    void requestBreakpoint(int line);
};

#endif // CODEVIEW_HPP
